[num_users, num_items]=size(train_rate_matrix_user);

mae_plot = zeros(maxepoch, 6);

if restart ==1
    restart=0;
    epoch=1;
    
    % Initializing symmetric weights and biases. 
    vishid_user = 0.1*randn(num_items, numhid);
    vishid_item = 0.1*randn(num_users, numhid);
    hidbiases_user = zeros(1,numhid);
    hidbiases_item = zeros(1,numhid);
    visbiases_user = zeros(1,num_items);
    visbiases_item = zeros(1,num_users);

    poshidprobs_user = zeros(num_users,numhid);
    poshidprobs_item = zeros(num_items,numhid);
    neghidprobs_user = zeros(num_users,numhid);
    neghidprobs_item = zeros(num_items,numhid);
    posprods_user = zeros(num_items,numhid);
    posprods_item = zeros(num_users,numhid);
    negprods_user = zeros(num_items,numhid);
    negprods_item = zeros(num_users,numhid);
    vishidinc_user = zeros(num_items,numhid);
    vishidinc_item = zeros(num_users,numhid);
    hidbiasinc_user = zeros(1,numhid);
    hidbiasinc_item = zeros(1,numhid);
    visbiasinc_user = zeros(1,num_items);
    visbiasinc_item = zeros(1,num_users);
end

%error_plot = zeros(1,maxepoch/5);
flag_rate_template_user = train_rate_matrix_user > 0;
%flag_rate_template_item = train_rate_matrix_item > 0;
posvisact_user = sum(train_rate_matrix_user);
posvisact_item = sum(train_rate_matrix_user');
tic
for epoch = epoch:maxepoch,
   
    errsum_user=0;
    errsum_item=0;
    for batch = 1:1,
       % negdata_user = train_rate_matrix_user;
       % CD = floor(epoch/20)+1;
        for pp=1:CD
            poshidprobs_user = 1./(1 + exp(-train_rate_matrix_user*vishid_user - repmat(hidbiases_user,num_users,1)));    
            
            if pp==1
                posprods_user    = train_rate_matrix_user' * poshidprobs_user;
                poshidact_user   = sum(poshidprobs_user);        
            end

	    %%%%%%%%% END OF POSITIVE PHASE  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %          poshidstates_user = poshidprobs_user > rand(num_users,numhid);

            %%%%%%%%% START NEGATIVE PHASE  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
            negdata_user = 1./(1 + exp(-poshidprobs_user*vishid_user' - repmat(visbiases_user,num_users,1)));
            %negdata_user = negdata_user.*flag_rate_template_user;
        end
        
        
      %  negdata_item = train_rate_matrix_item;
       % CD = floor(epoch/20)+1;
        for pp=1:CD
            poshidprobs_item = 1./(1 + exp(-train_rate_matrix_user'*vishid_item - repmat(hidbiases_item,num_items,1)));    
            
	    if pp==1
	        posprods_item    = train_rate_matrix_user * poshidprobs_item;
            poshidact_item   = sum(poshidprobs_item);
	    end
	    %%%%%%%%% END OF POSITIVE PHASE  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   %         poshidstates_item = poshidprobs_item > rand(num_items,numhid);

            %%%%%%%%% START NEGATIVE PHASE  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
            negdata_item = 1./(1 + exp(-poshidprobs_item*vishid_item' - repmat(visbiases_item,num_items,1)));
            %negdata_item = negdata_item.*flag_rate_template_item;
        end
        
        average_matrix = (negdata_item' + negdata_user)/2.*flag_rate_template_user;
        negdata_item = average_matrix';
        %negdata_user = average_matrix;
        
        %%%%%%%%%%%%  USER    %%%%%%%%%%%
        neghidprobs_user = 1./(1 + exp(-average_matrix*vishid_user - repmat(hidbiases_user,num_users,1)));   
        negprods_user  = average_matrix'*neghidprobs_user;
        neghidact_user = sum(neghidprobs_user);
        negvisact_user = sum(average_matrix); 
        %%%%%%%%%%%%   ITEM    %%%%%%%%%%%%%
        neghidprobs_item = 1./(1 + exp(-negdata_item*vishid_item - repmat(hidbiases_item,num_items,1)));   
        negprods_item  = negdata_item'*neghidprobs_item;
        neghidact_item = sum(neghidprobs_item);
        negvisact_item = sum(negdata_item); 

        %%%%%%%%% END OF NEGATIVE PHASE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        if epoch>5,
            momentum=finalmomentum;
        else
            momentum=initialmomentum;
        end;

        %%%%%%%%% UPDATE WEIGHTS AND BIASES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
        vishidinc_user = momentum*vishidinc_user + epsilonw*( (posprods_user-negprods_user)/num_users - weightcost*vishid_user);
        visbiasinc_user = momentum*visbiasinc_user + (epsilonvb/num_users)*(posvisact_user-negvisact_user);
        hidbiasinc_user = momentum*hidbiasinc_user + (epsilonhb/num_users)*(poshidact_user-neghidact_user);
        
        vishid_user = vishid_user + vishidinc_user;
        visbiases_user = visbiases_user + visbiasinc_user;
        hidbiases_user = hidbiases_user + hidbiasinc_user;
        
        
        vishidinc_item = momentum*vishidinc_item + epsilonw*( (posprods_item-negprods_item)/num_items - weightcost*vishid_item);
        visbiasinc_item = momentum*visbiasinc_item + (epsilonvb/num_items)*(posvisact_item-negvisact_item);
        hidbiasinc_item = momentum*hidbiasinc_item + (epsilonhb/num_items)*(poshidact_item-neghidact_item);
        
        vishid_item = vishid_item + vishidinc_item;
        visbiases_item = visbiases_item + visbiasinc_item;
        hidbiases_item = hidbiases_item + hidbiasinc_item;

        %%%%%%%%%%%%%%%% END OF UPDATES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
    end
    if mod(epoch,5)==0
        MAE_ui
        toc
        tic
    end
    %fprintf(1, 'epoch %4i error %6.1f  \n', epoch, errsum);
    %error_plot(1,epoch/5) = errsum;
end;

plot(test_mae);
